package db_utils

import (
	"dgo/goutils/utils"
	"strings"
)

type RecUpbuilderEx struct {
	FieldPrefix, FieldSuffix string

	keyfields []string
	uptable   string
	bb0       utils.BytesBuilder
	bb1       utils.BytesBuilder

	currentMap  map[string]interface{}
	originalMap map[string]interface{}
}

func NewRecUpbuilderEx() *RecUpbuilderEx {
	rval := &RecUpbuilderEx{}
	rval.Clear()
	return rval
}

func (this *RecUpbuilderEx) Clear() {
	if this.currentMap == nil || len(this.currentMap) > 0 {
		this.currentMap = make(map[string]interface{})
	}

	if this.originalMap == nil || len(this.originalMap) > 0 {
		this.originalMap = make(map[string]interface{})
	}
}

func (this *RecUpbuilderEx) IsKeyField(fieldname string) bool {
	return utils.StrIndexIgnoreCase(fieldname, this.keyfields...) != -1
}

func (this *RecUpbuilderEx) ConfigUptable(val string) {
	this.uptable = val
}

func (this *RecUpbuilderEx) ConfigKeyFields(keyfields string) {
	if len(keyfields) == 0 {
		this.keyfields = nil
		return
	}
	if strings.Contains(keyfields, ";") {
		this.keyfields = strings.Split(keyfields, ";")
	} else {
		this.keyfields = strings.Split(keyfields, ",")
	}
}

func (this *RecUpbuilderEx) buildWhere(keyfields []string) string {
	this.bb1.Cleanup()
	j := 0
	for _, k := range keyfields {
		if v, ok := this.originalMap[k]; ok {
			if j > 0 {
				this.bb1.WriteString(" AND ")
			}

			this.bb1.WriteString(this.FieldPrefix)
			this.bb1.WriteString(k)
			this.bb1.WriteString(this.FieldSuffix)
			this.bb1.WriteString("=")
			this.bb1.WriteString(ToSQLVal(v))

			j++
		}
	}

	return this.bb1.String()
}

func (this *RecUpbuilderEx) BuildDel() string {
	wherestr := this.buildWhere(this.keyfields)
	if len(wherestr) == 0 {
		return ""
	}
	this.bb0.Cleanup()
	this.bb0.AppendStrs("DELETE FROM ", this.uptable)
	this.bb0.AppendStrs(" WHERE ", wherestr)
	return this.bb0.String()
}

func (this *RecUpbuilderEx) BuildUpdate() string {
	wherestr := this.buildWhere(this.keyfields)
	if len(wherestr) == 0 {
		return ""
	}
	this.bb0.Cleanup()
	this.bb0.AppendStrs("UPDATE ", this.uptable, " SET ")
	j := 0
	for k, v := range this.currentMap {
		if j > 0 {
			this.bb0.WriteString(",")
		}
		this.bb0.WriteString(this.FieldPrefix)
		this.bb0.WriteString(k)
		this.bb0.WriteString(this.FieldSuffix)
		this.bb0.WriteString("=")
		this.bb0.WriteString(ToSQLVal(v))
		j++
	}

	if j == 0 {
		return ""
	}

	this.bb0.AppendStrs(" WHERE ", wherestr)
	return this.bb0.String()
}

func (this *RecUpbuilderEx) BuildInsert() string {
	this.bb0.Cleanup()
	this.bb1.Cleanup()
	this.bb0.Appendf("INSERT INTO %s (", this.uptable)
	this.bb1.WriteString(" VALUES(")
	j := 0
	for k, v := range this.currentMap {
		if j > 0 {
			this.bb0.WriteString(",")
			this.bb1.WriteString(",")
		}
		this.bb0.WriteString(this.FieldPrefix)
		this.bb0.WriteString(k)
		this.bb0.WriteString(this.FieldSuffix)
		this.bb1.WriteString(ToSQLVal(v))
		j++
	}
	this.bb0.WriteString(")")
	this.bb0.AppendBuilder(&this.bb1)
	this.bb0.WriteString(")")
	return this.bb0.String()
}

func (this *RecUpbuilderEx) SetOrignal(key string, val interface{}) {
	this.originalMap[key] = val
}

func (this *RecUpbuilderEx) SetCurrent(key string, val interface{}) {
	this.currentMap[key] = val
}
